package com.ydl.shopping.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ydl.shopping.core.dto.OrderDTO;
import com.ydl.shopping.domain.TbGoods;
import com.ydl.shopping.domain.TbOrder;
import com.ydl.shopping.domain.TbOrderDetail;
import com.ydl.shopping.exception.ServiceException;
import com.ydl.shopping.mapper.TbOrderMapper;
import com.ydl.shopping.service.ITbGoodsService;
import com.ydl.shopping.service.ITbOrderDetailService;
import com.ydl.shopping.service.ITbOrderService;
import com.ydl.shopping.utils.CacheUtil;
import com.ydl.shopping.utils.SecurityUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.logging.SimpleFormatter;
import java.util.stream.Collectors;

@Service
public class TbOrderServiceImpl extends ServiceImpl<TbOrderMapper, TbOrder> implements ITbOrderService {
    @Resource
    private ITbGoodsService goodsService;

    @Resource
    private ITbOrderDetailService orderDetailService;

    @Resource
    private CacheUtil cacheUtil;

    private final String cacheKey = "order:";

    @Override
    public QueryWrapper<TbOrder> queryWrapper(TbOrder entity) {
        QueryWrapper<TbOrder> queryWrapper = new QueryWrapper<>();
        Long userId = entity.getUserId();
        if (userId != null) {
            queryWrapper.eq("user_id", userId);
        }
        Integer status = entity.getStatus();
        if (status != null) {
            queryWrapper.eq("status", status);
        }

        return queryWrapper;
    }

    @Override
    public TbOrder queryByOrderNumber(String orderNumber) {
        return query().eq("order_number", orderNumber).one();
    }

    @Override
    public String createOrder(List<OrderDTO> orderDTOS) {
        // 1. 下单商品验证
        boolean anyMatch = orderDTOS.stream().anyMatch(item -> {
            Integer quantity = item.getQuantity();
            if (quantity == null) {
                return true;
            }
            return quantity < 1;
        });
        // 2. 判断是否存在下单数量低于1的商品
        if (anyMatch) {
            throw new ServiceException("下单商品数量不得少于1");
        }
        BigDecimal price = new BigDecimal(0);
        List<TbGoods> goodsList = new ArrayList<>();
        Long userId = SecurityUtil.getUserId();
        String userName = SecurityUtil.getUserName();
        // 3. 判断商品是否存在
        for (OrderDTO dto : orderDTOS) {
            // 获取商品ID
            Long goodsId = dto.getGoodsId();
            // 获取下单数量
            Integer quantity = dto.getQuantity();
            QueryWrapper<TbGoods> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("id", goodsId);
            queryWrapper.eq("status", 1);
            queryWrapper.eq("is_up", 1);
            // 根据ID查询商品信息
            TbGoods goods = goodsService.getOne(queryWrapper);
            // 判断商品信息是否为null
            if (goods == null) {
                throw new ServiceException("下单商品不存在或已下架");
            }
            // 判断商品库存数量是否足够
            Integer goodsQuantity = goods.getQuantity();
            if (goodsQuantity < quantity) {
                throw new ServiceException("下单商品库存不足");
            }
            price = price.add(goods.getUnitPrice().multiply(new BigDecimal(quantity)));
            goodsList.add(goods);
        }
        // 4. 生成订单号
        Date date = new Date();
        SimpleDateFormat simpleFormatter = new SimpleDateFormat("yyyyMMdd");
        // 获取当前时间戳
        long time = date.getTime();
        // 获取当前日期
        String dateStr = simpleFormatter.format(date);
        // 当前订单数
        long count = getOrderCount(dateStr);
        String orderNumber = time + dateStr + count;
        // 5. 创建订单
        TbOrder tbOrder = new TbOrder();
        tbOrder.setOrderNumber(orderNumber);
        tbOrder.setPrice(price);
        tbOrder.setStatus(1); // 待支付
        tbOrder.setUserId(userId);
        tbOrder.setCreateBy(userName);
        boolean save = save(tbOrder);
        if (!save) {
            throw new ServiceException("生成订单失败");
        }
        // 6. 保存订单详情
        Long orderId = tbOrder.getId();
        for (TbGoods goods : goodsList) {
            // 获取下单数量
            Integer quantity = orderDTOS.stream()
                    .filter(item -> item.getGoodsId().equals(goods.getId()))
                    .collect(Collectors.toList()).get(0).getQuantity();
            TbOrderDetail tbOrderDetail = new TbOrderDetail();
            tbOrderDetail.setOrderId(orderId);
            tbOrderDetail.setGoodsId(goods.getId());
            tbOrderDetail.setUnitPrice(goods.getUnitPrice());
            tbOrderDetail.setQuantity(quantity);
            tbOrderDetail.setCreateBy(userName);
            orderDetailService.save(tbOrderDetail);
            // 修改商品库存
            goods.setQuantity(goods.getQuantity() - quantity);
            goodsService.updateById(goods);
        }
        return orderNumber;
    }

    @Override
    public boolean cancelOrder(String orderNumber) {
        // 1、根据订单号查找订单
        TbOrder tbOrder = queryByOrderNumber(orderNumber);
        // 2、判断订单是否存在
        if (tbOrder == null) {
            throw new ServiceException("订单不存在或已关闭");
        }
        // 3、判断订单状态
        Integer status = tbOrder.getStatus();
        switch (status) {
            case 4 -> throw new ServiceException("订单已完成");
            case 3 -> throw new ServiceException("订单已发货");
            case 0 -> throw new ServiceException("订单已关闭");
        }
        // 4、订单取消
        // 4.1 获取订单编号
        Long id = tbOrder.getId();
        // 4.2 获取订单详细
        List<TbOrderDetail> orderDetails = orderDetailService.query().eq("order_id", id).list();
        // 4.3 商品库存退回
        for (TbOrderDetail orderDetail : orderDetails) {
            // 4.3.1 获取商品ID
            Long goodsId = orderDetail.getGoodsId();
            TbGoods byId = goodsService.getById(goodsId);

            // 4.3.2 获取下单数量
            Integer quantity = orderDetail.getQuantity();

            TbGoods tbGoods = new TbGoods();
            tbGoods.setId(goodsId);
            tbGoods.setQuantity(byId.getQuantity() + quantity);
            // 4.3.3 商品库存回退
            boolean update = goodsService.updateById(tbGoods);
            if (!update) {
                throw new ServiceException("取消订单失败");
            }
        }
        // 5、支付金额退还
        if (status.equals(2)) {
            // 退款业务代码。。。
            System.out.println("[取消订单]订单" + orderNumber + "已完成退款" + tbOrder.getPrice() + "元");
        }
        // 6、关闭订单
        tbOrder.setStatus(0);
        tbOrder.setRemark("取消订单");
        return updateById(tbOrder);
    }

    /**
     * 获取订单序号
     *
     * @param dateStr 日期字符串
     * @return 订单序号
     */
    private Long getOrderCount(String dateStr) {
        Long count = 0L;
        String key = cacheKey + "count:" + dateStr;
        String str = cacheUtil.getStr(key);
        if (StrUtil.isBlank(str)) {
            cacheUtil.setStr(key, "1");
            count = 1L;
        } else {
            count = cacheUtil.incrementStr(key);
        }
        return count;
    }
}
